﻿using System.Linq;
using Daemon.Common;
using Daemon.Common.Helpers;
using Daemon.Infrustructure.EF;
using Daemon.Repository.EF.Enums;
using Daemon.Repository.Contract;
using Daemon.Model;
using System;
using System.Linq.Expressions;
using System.Collections.Generic;

namespace Daemon.Repository.EF
{
    public class StudentRepository : Repository<Student>, IStudentRepository
    {
        protected override Expression<Func<Student, int>> PrimaryKeyExpression => r => r.Id;

        public StudentRepository(ApiDBContent context) : base(context)
        {
        }

        protected override void UpdateEntitiesBeforeCreate(IEnumerable<Student> entities, ApiDBContent context)
        {
            foreach (var entity in entities)
            {
               if (AuthInfo.UserEntity.SchoolId.HasValue)
                {
                    entity.SchoolId = AuthInfo.UserEntity.SchoolId.Value;
                }
                entity.AddUserId = AuthInfo.UserId;
            }
        }

        protected override IQueryable<Student> GetDbQuery(ApiDBContent context, bool isNoTracking = true)
        {
            var query = base.GetDbQuery(context, isNoTracking);
            return query.Where(r => !r.Deleted.HasValue || !r.Deleted.Value);
        }

        protected override IQueryable<Student> FilterByAuthInfo(IQueryable<Student> queryable, ApiDBContent context)
        {
            if (AuthInfo.IsAdmin)
            {
                return queryable;
            }

            queryable = queryable.Where(r => r.SchoolId == AuthInfo.UserEntity.SchoolId && r.AddUserId == AuthInfo.UserId);
            return queryable;
        }

        protected override IEnumerable<Student> IncludeRelationships(IEnumerable<Student> entities, ApiDBContent db)
        {
            SetStudentClassInfo(entities);

            SetStudentGradeInfo(entities);

            SetSchoolInfo(entities);

            return entities;
        }

        private void SetSchoolInfo(IEnumerable<Student> entities)
        {
            if (!RouteParameterHelper.CheckRouteParameter(RelationshipNames, StudentRelationship.SchoolInfo))
            {
                return;
            }

            var schoolIds = entities.Where(r => r.SchoolId.HasValue).Select(r => r.SchoolId).ToList();
            var schoolDic = Context.StudentSchools.Where(r => schoolIds.Contains(r.Id)).ToDictionary(r => r.Id, r => r.Name);
            foreach (var entity in entities)
            {
                if (schoolDic.TryGetValue(entity.ClassId, out string name))
                {
                    entity.SchoolName = name;
                }
            }
        }

        private void SetStudentClassInfo(IEnumerable<Student> entities)
        {
            if (!RouteParameterHelper.CheckRouteParameter(RelationshipNames, StudentRelationship.ClassInfo))
            {
                return;
            }

            var studentClassIds = entities.Where(r => r.ClassId != 0).Select(r => r.ClassId).ToList();
            var studentClassDic = Context.StudentClasses.Where(r => studentClassIds.Contains(r.Id)).ToDictionary(r => r.Id, r => r.Name);
            foreach (var entity in entities)
            {
                if (studentClassDic.TryGetValue(entity.ClassId, out string name))
                {
                    entity.ClassName = name;
                }
            }
        }

        private void SetStudentGradeInfo(IEnumerable<Student> entities)
        {
            if (!RouteParameterHelper.CheckRouteParameter(RelationshipNames, StudentRelationship.GradeInfo))
            {
                return;
            }

            var studentGradeIds = entities.Where(r => r.GradeId != 0).Select(r => r.GradeId).ToList();
            var studentGradeDic = Context.StudentGrade.Where(r => studentGradeIds.Contains(r.Id)).ToDictionary(r => r.Id, r => r.Name);
            foreach (var entity in entities)
            {
                if (studentGradeDic.TryGetValue(entity.GradeId, out string name))
                {
                    entity.GradeName = name;
                }
            }
        }
    }
}
